Package com.serotonin.m2m2.vmstat

Source Code of com.serotonin.m2m2.vmstat.VMStatDataSourceRT

/*
    Copyright (C) 2014 Infinite Automation Systems Inc. All rights reserved.
    @author Matthew Lohbihler
*/
package com.serotonin.m2m2.vmstat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.serotonin.m2m2.Common;
import com.serotonin.m2m2.i18n.TranslatableMessage;
import com.serotonin.m2m2.rt.dataImage.DataPointRT;
import com.serotonin.m2m2.rt.dataImage.PointValueTime;
import com.serotonin.m2m2.rt.dataSource.EventDataSource;

/**
* @author Matthew Lohbihler
*/
public class VMStatDataSourceRT extends EventDataSource implements Runnable {
    public static final int DATA_SOURCE_EXCEPTION_EVENT = 1;
    public static final int PARSE_EXCEPTION_EVENT = 2;

    private final Log log = LogFactory.getLog(VMStatDataSourceRT.class);
    private final VMStatDataSourceVO vo;
    private Process vmstatProcess;
    private BufferedReader in;
    private Map<Integer, Integer> attributePositions;
    private boolean terminated;

    public VMStatDataSourceRT(VMStatDataSourceVO vo) {
        super(vo);
        this.vo = vo;
    }

    //
    // /
    // / Lifecycle
    // /
    //
    @Override
    public void initialize() {
        super.initialize();
        String command;
        String osName = System.getProperty("os.name");
        if(osName.equals("Linux")){
            osName = "linux";
            command = "vmstat -n ";
        }
        else if(osName.startsWith("Win")){
            osName = "windows";
            raiseEvent(DATA_SOURCE_EXCEPTION_EVENT, System.currentTimeMillis(), true, new TranslatableMessage(
                    "event.initializationError", "OS: " + osName + " Not Supported"));
            return;
        }//since 0.9.0 ->
        else if(osName.equals("SunOS")){
            osName = "solaris";
            raiseEvent(DATA_SOURCE_EXCEPTION_EVENT, System.currentTimeMillis(), true, new TranslatableMessage(
                    "event.initializationError", "OS: " + osName + " Not Supported"));
            return;
        }
        else if(osName.equals("Mac OS X") || osName.equals("Darwin")){//os.name "Darwin" since 2.6.0
            osName = "mac_os_x";
            command = "vm_stat -n"; //TODO Implement this for OSX, output format is different
            raiseEvent(DATA_SOURCE_EXCEPTION_EVENT, System.currentTimeMillis(), true, new TranslatableMessage(
                    "event.initializationError", "OS: " + osName + " Not Supported"));
            return;
          
        }else{
            raiseEvent(DATA_SOURCE_EXCEPTION_EVENT, System.currentTimeMillis(), true, new TranslatableMessage(
                    "event.initializationError", "OS: " + osName + " Not Supported"));
            return;
        }

        switch (vo.getOutputScale()) {
        case VMStatDataSourceVO.OutputScale.LOWER_K:
            command += "-S k ";
            break;
        case VMStatDataSourceVO.OutputScale.UPPER_K:
            command += "-S K ";
            break;
        case VMStatDataSourceVO.OutputScale.LOWER_M:
            command += "-S m ";
            break;
        case VMStatDataSourceVO.OutputScale.UPPER_M:
            command += "-S M ";
            break;
        }

        command += vo.getPollSeconds();

        try {
            vmstatProcess = Runtime.getRuntime().exec(command);

            // Create the input stream readers.
            in = new BufferedReader(new InputStreamReader(vmstatProcess.getInputStream()));

            // Read the first two lines of output. They are the headers.
            in.readLine();
            String headers = in.readLine();

            // Create a mapping of attribute ids to split array positions.
            attributePositions = new HashMap<Integer, Integer>();
            headers = headers.trim();
            String[] headerParts = headers.split("\\s+");
            for (int i = 0; i < headerParts.length; i++) {
                int attributeId = -1;
                if ("r".equals(headerParts[i]))
                    attributeId = VMStatPointLocatorVO.Attributes.PROCS_R;
                else if ("b".equals(headerParts[i]))
                    attributeId = VMStatPointLocatorVO.Attributes.PROCS_B;
                else if ("swpd".equals(headerParts[i]))
                    attributeId = VMStatPointLocatorVO.Attributes.MEMORY_SWPD;
                else if ("free".equals(headerParts[i]))
                    attributeId = VMStatPointLocatorVO.Attributes.MEMORY_FREE;
                else if ("buff".equals(headerParts[i]))
                    attributeId = VMStatPointLocatorVO.Attributes.MEMORY_BUFF;
                else if ("cache".equals(headerParts[i]))
                    attributeId = VMStatPointLocatorVO.Attributes.MEMORY_CACHE;
                else if ("si".equals(headerParts[i]))
                    attributeId = VMStatPointLocatorVO.Attributes.SWAP_SI;
                else if ("so".equals(headerParts[i]))
                    attributeId = VMStatPointLocatorVO.Attributes.SWAP_SO;
                else if ("bi".equals(headerParts[i]))
                    attributeId = VMStatPointLocatorVO.Attributes.IO_BI;
                else if ("bo".equals(headerParts[i]))
                    attributeId = VMStatPointLocatorVO.Attributes.IO_BO;
                else if ("in".equals(headerParts[i]))
                    attributeId = VMStatPointLocatorVO.Attributes.SYSTEM_IN;
                else if ("cs".equals(headerParts[i]))
                    attributeId = VMStatPointLocatorVO.Attributes.SYSTEM_CS;
                else if ("us".equals(headerParts[i]))
                    attributeId = VMStatPointLocatorVO.Attributes.CPU_US;
                else if ("sy".equals(headerParts[i]))
                    attributeId = VMStatPointLocatorVO.Attributes.CPU_SY;
                else if ("id".equals(headerParts[i]))
                    attributeId = VMStatPointLocatorVO.Attributes.CPU_ID;
                else if ("wa".equals(headerParts[i]))
                    attributeId = VMStatPointLocatorVO.Attributes.CPU_WA;
                else if ("st".equals(headerParts[i]))
                    attributeId = VMStatPointLocatorVO.Attributes.CPU_ST;

                if (attributeId != -1)
                    attributePositions.put(attributeId, i);
            }

            // Read the first line of data. This is a summary of beginning of time until now, so it is no good for
            // our purposes. Just throw it away.
            in.readLine();

            returnToNormal(DATA_SOURCE_EXCEPTION_EVENT, System.currentTimeMillis());
        }
        catch (IOException e) {
            raiseEvent(DATA_SOURCE_EXCEPTION_EVENT, System.currentTimeMillis(), true, new TranslatableMessage(
                    "event.initializationError", e.getMessage()));
        }
    }

    @Override
    public void terminate() {
        super.terminate();

        terminated = true;

        // Stop the process.
        if (vmstatProcess != null)
            vmstatProcess.destroy();
    }

    @Override
    public void beginPolling() {
        if (vmstatProcess != null)
            new Thread(this, "VMStat data source").start();
    }

    public void run() {
        try {
            while (true) {
                String line = in.readLine();

                if (line == null) {
                    if (terminated)
                        break;
                    throw new IOException("no data");
                }
                line = line.trim();
                String[] parts = line.split("\\s+");
                readParts(parts);
                readError();
            }
        }
        catch (IOException e) {
            // Assume that the process was ended.
            readError();

            if (!terminated) {
                raiseEvent(DATA_SOURCE_EXCEPTION_EVENT, System.currentTimeMillis(), true, new TranslatableMessage(
                        "event.vmstat.process", e.getMessage()));
            }
        }
    }

    private void readParts(String[] parts) {
        TranslatableMessage error = null;
        long time = System.currentTimeMillis();

        synchronized (pointListChangeLock) {
            for (DataPointRT dp : dataPoints) {
                VMStatPointLocatorVO locator = ((VMStatPointLocatorRT) dp.getPointLocator()).getPointLocatorVO();

                Integer position = attributePositions.get(locator.getAttributeId());
                if (position == null) {
                    if (error != null)
                        error = new TranslatableMessage("event.vmstat.attributeNotFound",
                                locator.getConfigurationDescription());
                }
                else {
                    try {
                        String data = parts[position];
                        Double value = new Double(data);
                        dp.updatePointValue(new PointValueTime(value, time));
                    }
                    catch (NumberFormatException e) {
                        log.error("Weird. We couldn't parse the value " + parts[position]
                                + " into a double. attribute=" + locator.getAttributeId());
                    }
                    catch (ArrayIndexOutOfBoundsException e) {
                        log.error("Weird. We need element " + position + " but the vmstat data is only " + parts.length
                                + " elements long. The statistic " + Common.translate(VMStatPointLocatorVO.ATTRIBUTE_CODES.getKey(locator.getAttributeId())) + " is missing from the vmstat output.");
                        raiseEvent(DATA_SOURCE_EXCEPTION_EVENT, System.currentTimeMillis(), true, new TranslatableMessage(
                                "event.vmstat.process", "The statistic " + Common.translate(VMStatPointLocatorVO.ATTRIBUTE_CODES.getKey(locator.getAttributeId())) + " is missing from the vmstat output."));
                    }
                }
            }
        }

        if (error == null)
            returnToNormal(PARSE_EXCEPTION_EVENT, time);
        else
            raiseEvent(PARSE_EXCEPTION_EVENT, time, true, error);
    }

    private void readError() {
        Process p = vmstatProcess;
        if (p != null) {
            try {
                if (p.getErrorStream().available() > 0) {
                    StringBuilder errorMessage = new StringBuilder();
                    InputStreamReader err = new InputStreamReader(p.getErrorStream());
                    char[] buf = new char[1024];
                    int read;

                    while (p.getErrorStream().available() > 0) {
                        read = err.read(buf);
                        if (read == -1)
                            break;
                        errorMessage.append(buf, 0, read);
                    }

                    if (!terminated)
                        log.warn("Error message from vmstat process: " + errorMessage);
                }
            }
            catch (IOException e) {
                log.warn("Exception while reading error stream", e);
            }
        }
    }
}
TOP

Related Classes of com.serotonin.m2m2.vmstat.VMStatDataSourceRT

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.